# 提取图片的传统特征（HER2染色）

from skimage import feature
from sklearn.decomposition import PCA
from PIL import Image
from pylab import *
import os

# 特征路径
HER2_image_path = 'K:/formal_data/HER2/test_for_data_prepossing/'

# 图片路径
Her2_feature_path = '../../../data/txt/feature/'

# 各种倍数、等级下的图片路径
HER2_image_5X_g0_path = HER2_image_path + '/5X/g0/'
HER2_image_5X_g1_path = HER2_image_path + '/5X/g1/'
HER2_image_5X_g2_path = HER2_image_path + '/5X/g2/'
HER2_image_5X_g3_path = HER2_image_path + '/5X/g3/'
HER2_image_10X_g0_path = HER2_image_path + '/10X/g0/'
HER2_image_10X_g1_path = HER2_image_path + '/10X/g1/'
HER2_image_10X_g2_path = HER2_image_path + '/10X/g2/'
HER2_image_10X_g3_path = HER2_image_path + '/10X/g3/'
HER2_image_20X_g0_path = HER2_image_path + '/20X/g0/'
HER2_image_20X_g1_path = HER2_image_path + '/20X/g1/'
HER2_image_20X_g2_path = HER2_image_path + '/20X/g2/'
HER2_image_20X_g3_path = HER2_image_path + '/20X/g3/'

# 特征的保存路径
# 具体某个种类的特征
Her2_feature_5X_g0_path =  Her2_feature_path + 'glcm_' + '5X_g0.txt'
Her2_feature_5X_g1_path =  Her2_feature_path + 'glcm_' + '5X_g1.txt'
Her2_feature_5X_g2_path =  Her2_feature_path + 'glcm_' + '5X_g2.txt'
Her2_feature_5X_g3_path =  Her2_feature_path + 'glcm_' + '5X_g3.txt'
Her2_feature_10X_g0_path =  Her2_feature_path + 'glcm_' + '10X_g0.txt'
Her2_feature_10X_g1_path =  Her2_feature_path + 'glcm_' + '10X_g1.txt'
Her2_feature_10X_g2_path =  Her2_feature_path + 'glcm_' + '10X_g2.txt'
Her2_feature_10X_g3_path =  Her2_feature_path + 'glcm_' + '10X_g3.txt'
Her2_feature_20X_g0_path =  Her2_feature_path + 'glcm_' + '20X_g0.txt'
Her2_feature_20X_g1_path =  Her2_feature_path + 'glcm_' + '20X_g1.txt'
Her2_feature_20X_g2_path =  Her2_feature_path + 'glcm_' + '20X_g2.txt'
Her2_feature_20X_g3_path =  Her2_feature_path + 'glcm_' + '20X_g3.txt'

# 某个倍数下的特征路径
Her2_feature_5X_all_path = Her2_feature_path + 'glcm_' + '5X_all.txt'
Her2_feature_10X_all_path = Her2_feature_path + 'glcm_' + '10X_all.txt'
Her2_feature_20X_all_path = Her2_feature_path + 'glcm_' + '20X_all.txt'


# 提取 glcm 特征,并将特征写入txt文件中
def extract_glcm_feature(path_image):
    #存储所有样本的glcm特征
    feature_glcm_total = []
    for files in os.listdir(path_image):
        #存储单张图片的glcm特征
        textural_feature = []
        #以灰度模式读取图片
        image = array(Image.open(path_image + files).convert('L'))
        # 计算灰度共生矩阵
        # distances原来是5
        glcm = feature.greycomatrix(image, [5], [0], 256, symmetric=True, normed=True)
        # 得到不同统计量
        textural_feature.append(feature.greycoprops(glcm, 'contrast')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'dissimilarity')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'homogeneity')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'ASM')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'energy')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'correlation')[0, 0])
        # 每遍历一张图片，将该图片的特征向量拼接到下一行
        feature_glcm_total.append(textural_feature)
    # 归一化
    # textural_feature_nor = MaxMinNormalization(feature_glcm_total)
    return feature_glcm_total

# 提取 lbp 特征（没用到）
def extract_lbp_feature(path_image):
    radius = 1;
    n_point = radius * 8;
    textural_feature_total = []
    for files in os.listdir(path_image):
        image = array(Image.open(path_image + files).convert('L'))
        # thresh = threshold_otsu(image)
        # binary = image > thresh
        # 计算lbp特征
        lbp_feature = feature.local_binary_pattern(image, n_point, radius)
        # 统计直方图
        lbp_hist = np.histogram(lbp_feature, bins=256)
        # 每遍历一张图片，将该图片的特征向量添加到list后面
        textural_feature_total.append(lbp_hist[0])
    # 归一化
    # textural_feature_nor = MaxMinNormalization(textural_feature_total)
    return textural_feature_total

# 提取 hessian 特征（没用到）
def extract_hessian_feature(path_image):
    radius = 1;
    n_point = radius * 8;
    textural_feature_total = []
    for files in os.listdir(path_image):
        image = array(Image.open(path_image + files))
        Hrr, Hrc, Hcc = feature.hessian_matrix(image, sigma=0.1, order='rc')
        # 计算hessian特征
        hessian_feature = feature.hessian_matrix_det(image)
        # 统计直方图
        hessian_hist = np.histogram(hessian_feature, bins=256)
        # 每遍历一张图片，将该图片的特征向量添加到list后面
        textural_feature_total.append(hessian_hist[0])
    return textural_feature_total

# n_components:保留下来的特征的个数
# PCA 特征降维（没用到）
def get_feature_pca(textural_feature_total):
    lbp_feature_array = np.array(textural_feature_total)
    pca = PCA(n_components=39)
    lbp_feature_pca = pca.fit(lbp_feature_array).transform(lbp_feature_array)
    return lbp_feature_pca

# 将glcm特征和lbp特征按照libsvm格式添加到统一 txt文件中（没用到）
def create_txt(path_positive,path_negative, path_svm, label_p, label_n):
    #提取正样本的glcm特征
    glcm_feature_p = extract_glcm_feature(path_positive)
    #提取负样本的glcm特征
    glcm_feature_n = extract_glcm_feature(path_negative)
    #提取正样本的lbp特征
    lbp_feature_p = extract_lbp_feature(path_positive)
    #提取负样本的lbp特征
    lbp_feature_n = extract_lbp_feature(path_negative)
    #对lbp特征进行PCA降维
    lbp_pca_p = get_feature_pca(lbp_feature_p)
    lbp_pca_n = get_feature_pca(lbp_feature_n)
    f = open(path_svm, 'w+')
    #正样本图片数量
    data_p_length = len(glcm_feature_p);
    #负样本图片数量
    data_n_length = len(glcm_feature_n);
    #代表一张图片的glcm特征是多少维向量
    glcm_length = len(glcm_feature_p[0]);
    # 代表一张图片的lbp特征是多少维向量
    lbp_length = len(lbp_pca_p[0])

    for j in range(0, data_p_length):
        #将每张图片的标签写入txt
        f.write("%i "%label_p)
        #若提取的cnn特征个数为100，则传统特征标记从101开始
        #将glcm特征写入txt
        for i in range(0,glcm_length):
            vec_temp = glcm_feature_p[j]
            newcontext = "%i:"%(i + 101) + "%f"%(vec_temp[i]) + " "
            f.write(newcontext)
        #将lbp特征写入txt
        for i in range(0, lbp_length):
            vec_temp = lbp_pca_p[j]
            newcontext = "%i:"%(i +glcm_length+ 101) + "%f"%(vec_temp[i]) + " "
            f.write(newcontext)
        f.write('\n')
    for j in range(0, data_n_length):
        f.write("%i "%label_n)
        for i in range(0,glcm_length):
            vec_temp = glcm_feature_n[j]
            newcontext = "%i:"%(i + 101) + "%f"%(vec_temp[i]) + " "
            f.write(newcontext)
        for i in range(0, lbp_length):
            vec_temp = lbp_pca_n[j]
            newcontext = "%i:" % (i + glcm_length + 101) + "%f" % (vec_temp[i]) + " "
            f.write(newcontext)
        f.write('\n')

# 满足四种等级的灰度共生矩阵特征文件生成
def create_glcm_txt(path_g0,path_g1,path_g2,path_g3,
                    path_lpa_g0, path_lpa_g1,path_lpa_g2,path_lpa_g3,
                    label_g0, label_g1, label_g2, label_g3):
    # g0特征
    glcm_feature_g0 = extract_glcm_feature(path_g0)
    # g1特征
    glcm_feature_g1 = extract_glcm_feature(path_g1)
    # g2特征
    glcm_feature_g2 = extract_glcm_feature(path_g2)
    # g3特征
    glcm_feature_g3 = extract_glcm_feature(path_g3)



    f0 = open(path_lpa_g0, 'w+')
    for j in range(0, len(glcm_feature_g0)):
        f0.write("%i "%label_g0)
        for i in range(0,len(glcm_feature_g0[0])):
            vec_temp = glcm_feature_g0[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f0.write(newcontext)
        f0.write('\n')

    f1 = open(path_lpa_g1, 'w+')
    for j in range(0, len(glcm_feature_g1)):
        f1.write("%i "%label_g1)
        for i in range(0,len(glcm_feature_g1[0])):
            vec_temp = glcm_feature_g1[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f1.write(newcontext)
        f1.write('\n')

    f2 = open(path_lpa_g2, 'w+')
    for j in range(0, len(glcm_feature_g2)):
        f2.write("%i "%label_g2)
        for i in range(0,len(glcm_feature_g2[0])):
            vec_temp = glcm_feature_g2[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f2.write(newcontext)
        f2.write('\n')

    f3 = open(path_lpa_g3, 'w+')
    for j in range(0, len(glcm_feature_g3)):
        f3.write("%i "%label_g3)
        for i in range(0,len(glcm_feature_g3[0])):
            vec_temp = glcm_feature_g3[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f3.write(newcontext)
        f3.write('\n')

# 满足四种等级的灰度共生矩阵特征文件生成（存为一个总的txt文件，一般用于训练）
def create_glcm_in_one_txt(path_g0,path_g1,path_g2,path_g3,
                    path_lpa_all,
                    label_g0, label_g1, label_g2, label_g3):
    # g0特征
    glcm_feature_g0 = extract_glcm_feature(path_g0)
    # g1特征
    glcm_feature_g1 = extract_glcm_feature(path_g1)
    # g2特征
    glcm_feature_g2 = extract_glcm_feature(path_g2)
    # g3特征
    glcm_feature_g3 = extract_glcm_feature(path_g3)



    f_all = open(path_lpa_all, 'w+')
    for j in range(0, len(glcm_feature_g0)):
        f_all.write("%i "%label_g0)
        for i in range(0,len(glcm_feature_g0[0])):
            vec_temp = glcm_feature_g0[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g1)):
        f_all.write("%i "%label_g1)
        for i in range(0,len(glcm_feature_g1[0])):
            vec_temp = glcm_feature_g1[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g2)):
        f_all.write("%i "%label_g2)
        for i in range(0,len(glcm_feature_g2[0])):
            vec_temp = glcm_feature_g2[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g3)):
        f_all.write("%i "%label_g3)
        for i in range(0,len(glcm_feature_g3[0])):
            vec_temp = glcm_feature_g3[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

# 提取某一个文件夹内要被归类的图片数据集
def create_glcm_txt_for_classifying(path_classify,
                    path_svm_classify,
                    label_classify):
    # 提取正样本的glcm特征
    glcm_feature_classify = extract_glcm_feature(path_classify)
    # 提取负样本的glcm特征
    # glcm_feature_n = extract_glcm_feature(path_negative)
    f1 = open(path_svm_classify, 'w+')
    for j in range(0, len(glcm_feature_classify)):
        f1.write("%i " % label_classify)
        for i in range(0, len(glcm_feature_classify[0])):
            vec_temp = glcm_feature_classify[j]
            newcontext = "%i:" % (i + 1) + "%f" % (vec_temp[i]) + " "
            f1.write(newcontext)
        f1.write('\n')



if __name__ == '__main__':
    # create_txt(path_positive,path_negative, path_svm, 2, 1)
    # HER2染色的切片提取特征
    # create_glcm_txt(HER2_image_5X_g0_path,HER2_image_5X_g1_path, HER2_image_5X_g2_path, HER2_image_5X_g3_path,
    #                 Her2_feature_5X_g0_path, Her2_feature_5X_g1_path, Her2_feature_5X_g2_path, Her2_feature_5X_g3_path,
    #                 1, 2, 3, 4)

    create_glcm_txt(HER2_image_10X_g0_path,HER2_image_10X_g1_path, HER2_image_10X_g2_path, HER2_image_10X_g3_path,
                    Her2_feature_10X_g0_path, Her2_feature_10X_g1_path, Her2_feature_10X_g2_path, Her2_feature_10X_g3_path,
                    1, 2, 3, 4)

    # create_glcm_txt(HER2_image_20X_g0_path,HER2_image_20X_g1_path, HER2_image_20X_g2_path, HER2_image_20X_g3_path,
    #                 Her2_feature_20X_g0_path, Her2_feature_20X_g1_path, Her2_feature_20X_g2_path, Her2_feature_20X_g3_path,
    #                 1, 2, 3, 4)

    # create_glcm_in_one_txt(HER2_image_20X_g0_path,HER2_image_20X_g1_path, HER2_image_20X_g2_path, HER2_image_20X_g3_path,
    #                        Her2_feature_20X_all_path,
    #                         1, 2, 3, 4)

    create_glcm_in_one_txt(HER2_image_10X_g0_path,HER2_image_10X_g1_path, HER2_image_10X_g2_path, HER2_image_10X_g3_path,
                           Her2_feature_10X_all_path,
                            1, 2, 3, 4)